#include "contactservice.hpp"
#include "httplib.h"
#include <string>
#include "exception.hpp"
#include <sstream>
const std::string SERVER_IP = "115.190.60.239";
const int SERVER_PORT = 8089;
using namespace std;

void ContactsServer::addContact()
{

    httplib::Client cli(SERVER_IP, SERVER_PORT);

    add_contact_req::AddContactRequest req;
    // 给用户输入对应信息构成req：

    BuildAddContactRequest(&req);

    // 序列化
    string req_str;

    bool ok1 = req.SerializeToString(&req_str);

    if (!ok1)
        throw Exception("AddContactRequest序列化失败!");

    // 发送psot请求
    auto res = cli.Post("/contacts/add", req_str, "application/protobuf"); // url即服务端对应的post对应的url来接收；其次就是对应的请求头类型：Content-Type:

    if (!res)
    {

        string err_des;
        err_des.append("/contacts/add 链接错误！错误信息：").append(httplib::to_string(res.error()));

        throw Exception(err_des);
    }

    // 拿到对应信息进行反序列化：
    add_contact_res::AddContactResponse resp;

    bool ok2 = resp.ParseFromString(res->body);

    // 反序列化+网络传输失败：
    if (!res->status && !ok2)
    {

        stringstream des;
        des << "post '/contacts/add/' 失败 " << " 状态:(" << res->status << ") " << " 原因： ( " << res->reason << ") ";
        throw Exception(des.str());
    }
    // 反序列化成功但是状态错误或者未设置：
    else if (!res->status)
    {

        stringstream des;
        des << "post '/contacts/add/' 失败 " << " 状态:(" << res->status << ") " << " 原因： ( " << res->reason << ") 错误描述： ( " << resp.base_resp().error_desc() << " )";
        throw Exception(des.str());
    }

    // 服务端操作错误：
    else if (!resp.base_resp().success())
    {
        stringstream des;

        des << "post '/contacts/add/' 失败 " << "错误描述：（ " << resp.base_resp().error_desc() << " )";

        throw Exception(des.str());
    }

    // 成获取对应map映射的uid：
    std::cout << "---> 新增联系人成功，联系人ID：" << resp.uid() << std::endl;
}

void ContactsServer::delContact()
{
    httplib::Client cli(SERVER_IP, SERVER_PORT);
    del_req::DelContactRequest del_req;
    std::cout << "请输入要删除的联系人id: ";
    std::string uid;
    getline(std::cin, uid);
    del_req.set_uid(uid);

    // 进行序列化：
    std::string req_str;
    if (!del_req.SerializeToString(&req_str))
    {
        throw Exception("DelContactRequest序列化失败!");
    }

    // 发送请求:
    auto res = cli.Post("/contacts/del", req_str, "application/protobuf"); // url即服务端对应的post对应的url来接收；其次就是对应的请求头类型：Content-Type:

    if (!res)
    {

        string err_des;
        err_des.append("/contacts/del 链接错误！错误信息：").append(httplib::to_string(res.error()));

        throw Exception(err_des);
    }

    // 拿到对应信息进行反序列化：
    del_res::DelContactResponse resp;

    bool ok2 = resp.ParseFromString(res->body);

    // 反序列化+网络传输失败：
    if (!res->status && !ok2)
    {

        stringstream des;
        des << "post '/contacts/del' 失败 " << " 状态:(" << res->status << ") " << " 原因： ( " << res->reason << ") ";
        throw Exception(des.str());
    }
    // 反序列化成功但是状态错误或者未设置：
    else if (!res->status)
    {

        stringstream des;
        des << "post '/contacts/del' 失败 " << " 状态:(" << res->status << ") " << " 原因： ( " << res->reason << ") 错误描述： ( " << resp.base_resp().error_desc() << " )";
        throw Exception(des.str());
    }

    // 服务端操作错误：
    else if (!resp.base_resp().success())
    {
        stringstream des;

        des << "post '/contacts/del' 失败 " << "错误描述：（ " << resp.base_resp().error_desc() << " )";

        throw Exception(des.str());
    }

    // 成获取对应map映射的uid：
    std::cout << "---> 删除联系人成功，联系人ID：" << resp.uid() << std::endl;
}

void ContactsServer::findContact()
{
    httplib::Client cli(SERVER_IP, SERVER_PORT);

    // 用户输入：
    find_one_req::FindOneContactRequest req;
    std::cout << "请输入要查询的联系人id: ";
    std::string uid;
    getline(std::cin, uid);
    req.set_uid(uid);

    // 进行序列化：
    std::string req_str;
    if (!req.SerializeToString(&req_str))
    {
        throw Exception("DelContactRequest序列化失败!");
    }

    // 进行post请求发送：

    auto res = cli.Post("/contacts/find-one", req_str, "application/protobuf");
    if (!res)
    {

        string err_des;
        err_des.append("/contacts/find-one 链接错误！错误信息：").append(httplib::to_string(res.error()));

        throw Exception(err_des);
    }

    // 拿到对应信息进行反序列化：
    find_one_res::FindOneContactResponse resp;

    bool ok2 = resp.ParseFromString(res->body);

    // 反序列化+网络传输失败：
    if (!res->status && !ok2)
    {

        stringstream des;
        des << "post '/contacts/find-one' 失败 " << " 状态:(" << res->status << ") " << " 原因： ( " << res->reason << ") ";
        throw Exception(des.str());
    }
    // 反序列化成功但是状态错误或者未设置：
    else if (!res->status)
    {

        stringstream des;
        des << "post '/contacts/find-one' 失败 " << " 状态:(" << res->status << ") " << " 原因： ( " << res->reason << ") 错误描述： ( " << resp.base_res().error_desc() << " )";
        throw Exception(des.str());
    }

    // 服务端操作错误：
    else if (!resp.base_res().success())
    {
        stringstream des;

        des << "post '/contacts/find-one' 失败 " << "错误描述：（ " << resp.base_res().error_desc() << " )";

        throw Exception(des.str());
    }

    // 成获取对应map映射的uid：
    std::cout << "---> 查询ID：" << resp.uid() << " 的联系人成功，信息如下：" << std::endl;

    PrintFindContactPeople(resp);
}

void ContactsServer::findContacts()
{

    httplib::Client cli(SERVER_IP, SERVER_PORT);

    auto res = cli.Get("/contacts/find-all");

    if (!res)
    {

        string err_des;
        err_des.append("/contacts/find-all 链接错误！错误信息：").append(httplib::to_string(res.error()));

        throw Exception(err_des);
    }

    // 拿到对应信息进行反序列化：
    find_all_contacts_resp::FindAllContactsResponse resp;

    bool ok2 = resp.ParseFromString(res->body);

    // 反序列化+网络传输失败：
    if (!res->status && !ok2)
    {

        stringstream des;
        des << "post '/contacts/find-all' 失败 " << " 状态:(" << res->status << ") " << " 原因： ( " << res->reason << ") ";
        throw Exception(des.str());
    }
    // 反序列化成功但是状态错误或者未设置：
    else if (!res->status)
    {

        stringstream des;
        des << "post '/contacts/find-all' 失败 " << " 状态:(" << res->status << ") " << " 原因： ( " << res->reason << ") 错误描述： ( " << resp.base_resp().error_desc() << " )";
        throw Exception(des.str());
    }

    // 服务端操作错误：
    else if (!resp.base_resp().success())
    {
        stringstream des;

        des << "post '/contacts/find-all' 失败 " << "错误描述：（ " << resp.base_resp().error_desc() << " )";

        throw Exception(des.str());
    }
    printAllContactPeople(resp);
}

// 私有成员；类内调用：

void ContactsServer::printAllContactPeople(find_all_contacts_resp::FindAllContactsResponse resp)
{

    if (0 == resp.contacts_size())
    {
        std::cout << "还未添加任何联系人" << std::endl;
        return;
    }
    for (auto contact : resp.contacts())
    {
        std::cout << "联系人姓名: " << contact.name() << " 联系人ID：" << contact.uid() << std::endl;
    }
}

void ContactsServer::PrintFindContactPeople(find_one_res::FindOneContactResponse resp)
{

    std::cout << "姓名：" << resp.name() << std::endl;
    std::cout << "年龄：" << resp.age() << std::endl;
    for (auto &phone : resp.phone())
    {
        int j = 1;
        std::cout << "电话" << j++ << ": " << phone.number();
        std::cout << "  (" << phone.PhoneType_Name(phone.type()) << ")" << std::endl;
    }
    if (resp.remark_size())
    {
        std::cout << "备注信息: " << std::endl;
    }
    for (auto it = resp.remark().cbegin(); it != resp.remark().cend(); ++it)
    {
        std::cout << "    " << it->first << ": " << it->second << std::endl;
    }
}
void ContactsServer::BuildAddContactRequest(add_contact_req::AddContactRequest *req)
{

    std::cout << "请输入联系人姓名: ";
    std::string name;
    getline(std::cin, name);
    req->set_name(name);

    std::cout << "请输入联系人年龄: ";
    int age;
    std::cin >> age;
    req->set_age(age);
    std::cin.ignore(256, '\n');

    for (int i = 1;; i++)
    {
        std::cout << "请输入联系人电话" << i << "(只输入回车完成电话新增): ";
        std::string number;
        getline(std::cin, number);
        if (number.empty())
        {
            break;
        }
        add_contact_req::AddContactRequest_Phone *phone = req->add_phone();
        phone->set_number(number);

        std::cout << "选择此电话类型 (1、移动电话   2、固定电话) : ";
        int type;
        std::cin >> type;
        std::cin.ignore(256, '\n');
        switch (type)
        {
        case 1:
            phone->set_type(add_contact_req::AddContactRequest_Phone_PhoneType::AddContactRequest_Phone_PhoneType_MP);
            break;
        case 2:
            phone->set_type(add_contact_req::AddContactRequest_Phone_PhoneType::AddContactRequest_Phone_PhoneType_TEL);
            break;
        default:
            std::cout << "----非法选择，使用默认值！" << std::endl;
            break;
        }


    }
     for(int i = 1; ; i++) {
        std::cout << "请输入备注" << i << "标题 (只输入回车完成备注新增): ";
        std::string remark_key;
        getline(std::cin, remark_key);
        if (remark_key.empty()) {
            break;
        }

        std::cout << "请输入备注" << i << "内容: ";
        std::string remark_value;
        getline(std::cin, remark_value);
        req->mutable_remark()->insert({remark_key, remark_value});
}
}
